﻿using System;
using System.Collections.Generic;
using System.Threading;
using NUnit.Framework;

namespace Errordite.Client.v2._0.Tests
{
    [TestFixture]
    public class ErrorditeScopeTests
    {
        
        [Test]
        public void Nesting()
        {
            using (new ErrorditeScope(() => new Dictionary<string, string>()
                {
                    {"A", "A"}
                }))
            {
                Assert.That(ErrorditeScope.Data.Count, Is.EqualTo(1));
                Assert.That(ErrorditeScope.Data.ContainsKey("A"));

                using (var s1 = new ErrorditeScope(() => new Dictionary<string, string>()
                    {
                        {"B", "B"}
                    }))
                {
                    Assert.That(ErrorditeScope.Data.Count, Is.EqualTo(2));
                    Assert.That(ErrorditeScope.Data.ContainsKey("A"));
                    Assert.That(ErrorditeScope.Data.ContainsKey("B"));
                    s1.Complete();
                }

                using (var s2 = new ErrorditeScope(() => new Dictionary<string, string>()
                    {
                        {"C", "C"}
                    }))
                {
                    Assert.That(ErrorditeScope.Data.Count, Is.EqualTo(2));
                    Assert.That(ErrorditeScope.Data.ContainsKey("A"));
                    Assert.That(ErrorditeScope.Data.ContainsKey("C"));
                    
                }

                Assert.That(ErrorditeScope.Data.Count, Is.EqualTo(2));
                Assert.That(ErrorditeScope.Data.ContainsKey("A"));
                Assert.That(ErrorditeScope.Data.ContainsKey("C"));
            } 

            Assert.That(ErrorditeScope.Data, Is.Null);
        }


       [Test]
       public void DataIsThreadStatic()
       {
           var o = new object();

           Func<Dictionary<string, string>> method = () => null;
           using (new ErrorditeScope(() => new Dictionary<string, string>()
               {
                   {"A", "A"}
               }))
           {
               Assert.That(ErrorditeScope.Data.Count, Is.EqualTo(1));

               Dictionary<string, string> dataFromOtherThread = null;
               try
               {
                   Monitor.Enter(o);

                   ThreadPool.QueueUserWorkItem(
                       delegate
                           {
                               using (new ErrorditeScope(() => new Dictionary<string, string>(){
                                               {"B", "B"}
                                           }))
                               lock (o)
                               {
                                   //Monitor.Wait(o);
                                   Console.WriteLine("thread start");

                                   dataFromOtherThread = ErrorditeScope.Data;

                                   Monitor.Pulse(o);
                               }
                               //
                               //Monitor.Exit(o);

                           });
                   Monitor.Wait(o);

               }
               finally
               {
                   Monitor.Exit(o);
               }


               Assert.That(ErrorditeScope.Data.Count, Is.EqualTo(1));
               Assert.That(ErrorditeScope.Data.ContainsKey("A"));
               Assert.That(dataFromOtherThread.Count, Is.EqualTo(1));
               Assert.That(dataFromOtherThread.ContainsKey("B"));
           }
       } 

        
    }
}